<cfcomponent name="LightBaseBeanConfig" extends="BaseConfigObject" hint="A LightWire configuration bean.">
<!--- 
BEAN DEFINITION SYNTAX
SINGLETONS:
addSingleton(FullClassPath, NameList)
Adds the definition for a given Singleton to the config file.
- FullClassPath:string:required - The full class path to the bean including its name. E.g. for com.UserService.cfc it would be com.UserService. 
- BeanName:string:optional - An optional name to be able to use to refer to this bean. If you don't provide this, the name of the bean will be used as a default. E.g. for com.UserService, it'll be named UserService unless you put something else here. If you put UserS, it'd be available as UserS, but NOT as UserService.

addSingletonFromFactory(FactoryBean, FactoryMethod, BeanName)
Adds the definition for a given Singleton that is created by a factory to the config file.
- FactoryBean:string:required - The name of the factory to use to create this bean (the factory must also have been defined as a Singleton in the LightWire config file).
- FactoryMethod:string:required - The name of the method to call on the factory bean to create this bean.
- BeanName:string:required - The required name to use to refer to this bean. 

TRANSIENTS:
addTransient(FullClassPath, NameList)
Adds the definition for a given Transient to the config file.
- FullClassPath:string:required - The full class path to the bean including its name. E.g. for com.UserBean.cfc it would be com.UserBean.
- BeanName:string:optional - An optional name to be able to use to refer to this bean. If you don't provide this, the name of the bean will be used as a default. E.g. for com.UserBean, it'll be named UserService unless you put something else here. If you put User, it'd be available as User, but NOT as UserBean.

addTransientFromFactory(FactoryBean, FactoryMethod, BeanName)
Adds the definition for a given Transient that is created by a factory to the config file.
- FactoryBean:string:required - The name of the factory to use to create this bean (the factory must also have been defined as a Singleton in the LightWire config file).
- FactoryMethod:string:required - The name of the method to call on the factory bean to create this bean.
- BeanName:string:required - The required name to use to refer to this bean. 

BEAN Dependency and PROPERTIES
Once you have defined a given bean, you also want to describe its Dependency and properties. Any bean can have 0..n constructor, setter and/or mixin Dependency and properties. Dependency handle LightWire initialized objects that need to be injected into your beans. Properties handle all other elements (strings, bits, structs, etc.). Please note: constructor Dependency are passed to the init() method, so you need a correspondingly named argument in your init file. Setter Dependency are injected using set#BeanName#() after calling the init() method but before returning the bean, so you need to have the appropriate setter. Mixin injections are auto injected into variables scope for you after calling the init() method but before returning the bean, but you don't need to have a setter() method - it used a generic setter injected automatically into all of your beans (lightwireMixin()).

addConstructorDependency(BeanName, InjectedBeanName, PropertyName)
Adds one or more constructor Dependency to a bean. If you call this more than once on the same bean, the additional Dependency will just be added to the list so it is valid to call this multiple times to build up a dependency list if required.
- BeanName:string:required - The name of the bean (Singleton or Transient) to add the Dependency to. You MUST have defined the bean using addSingleton() AddTransient(), addSingletonFromFactory() or addTransientFromFactory() before you add Dependency to the bean.
- InjectedBeanName:string:required - The name of the bean to inject.
- PropertyName:string:optional - The optional property name to pass the bean into. Defaults to the bean name if not provided.

addSetterDependency(BeanName, InjectedBeanName, PropertyName)
Adds one or more setter Dependency to a bean. If you call this more than once on the same bean, the additional Dependency will just be added to the list so it is valid to call this multiple times to build up a dependency list if required.
- BeanName:string:required - The name of the bean (Singleton or Transient) to add the Dependency to. You MUST have defined the bean using addSingleton() AddTransient(), addSingletonFromFactory() or addTransientFromFactory() before you add Dependency to the bean.
- InjectedBeanName:string:required - The name of the bean to inject.
- PropertyName:string:optional - The optional property name to pass the bean into. Defaults to the bean name if not provided.

addMixinDependency(BeanName, InjectedBeanName, PropertyName)
Adds one or more mixin Dependency to a bean. If you call this more than once on the same bean, the additional Dependency will just be added to the list so it is valid to call this multiple times to build up a dependency list if required.
- BeanName:string:required - The name of the bean (Singleton or Transient) to add the Dependency to. You MUST have defined the bean using addSingleton() AddTransient(), addSingletonFromFactory() or addTransientFromFactory() before you add Dependency to the bean.
- InjectedBeanName:string:required - The name of the bean to inject.
- PropertyName:string:optional - The optional property name to pass the bean into. Defaults to the bean name if not provided.

addConstructorProperty(PropertyName, PropertyValue)
Adds a constructor property to a bean. 
- BeanName:string:required - The name of the bean (Singleton or Transient) to add the property to. You MUST have defined the bean using addSingleton() AddTransient(), addSingletonFromFactory() or addTransientFromFactory() before you add properties to the bean.
- PropertyName:string:required - The name of the property to add.
- PropertyValue:any:required - The value of the property to add. Can be of any simple or complex type (anything from a string or a boolean to a struct or even an object that isn't being managed by LightWire).

addSetterProperty(PropertyName, PropertyValue)
Adds a setter property to a bean. 
- BeanName:string:required - The name of the bean (Singleton or Transient) to add the property to. You MUST have defined the bean using addSingleton() AddTransient(), addSingletonFromFactory() or addTransientFromFactory() before you add properties to the bean.
- PropertyName:string:required - The name of the property to add.
- PropertyValue:any:required - The value of the property to add. Can be of any simple or complex type (anything from a string or a boolean to a struct or even an object that isn't being managed by LightWire).

addMixinProperty(PropertyName, PropertyValue)
Adds a constructor property to a bean. 
- BeanName:string:required - The name of the bean (Singleton or Transient) to add the property to. You MUST have defined the bean using addSingleton() AddTransient(), addSingletonFromFactory() or addTransientFromFactory() before you add properties to the bean.
- PropertyName:string:required - The name of the property to add.
- PropertyValue:any:required - The value of the property to add. Can be of any simple or complex type (anything from a string or a boolean to a struct or even an object that isn't being managed by LightWire).
--->
	
	<cffunction name="init" output="false" returntype="any" hint="I initialize the config bean.">
		<cfargument name="ExternalConfigPath" type="string" default="" />
		<cfargument name="ExternalConfigSection" type="string" default="" />
		<!--- Firstly let us set up default configuration parameters --->
		<cfscript>
			var cfg = structNew();
			var cmdCollection = structNew();
			//This is the current build number of Kalendar - It needs to be the first thing configured
			cfg.KalendarBuildNumber = '1.0';

			//This is the public http path to the admin css directory. It must end with a slash '/'
			cfg.AdminCSSPath = '/kalendar/admin/common/css/';		
			//This is the title of your instance of kalendar
			cfg.AppTitle = "Kalendar - " & cfg.KalendarBuildNumber;
			//This is the path to the common.cfc directory. It must end with a dot '.'
			cfg.CFCPath = 'kalendar.common.cfc.';
			//This is the url parameter needed to reload the Kalendar Settings
			cfg.CurrentMode = 'Development';
			//This is the public http path to the css directory. It must end with a slash '/'
			cfg.CSSPath = '/kalendar/common/css/';
			//This is the path to the custom tags directory. It must end with a slash '/'
			cfg.CustomTagPath = '/kalendar/common/tags/';
			//This is the Database Platform used for Kalendar. Possible Values:  MSSQL, MYSQL
			cfg.DBType = 'MSSQL';
			//This is the default Kalendar View
			cfg.DefaultView = 'list';
			//This is the default Category ID. Set this to the category ID in the database representing your default category choice in Kalendar
			cfg.DefaultCategoryID = '00000000-0000-0000-0000000000000000';
			//This is the name of the datasource in the CF Administrator for Kalendar
			cfg.DSN = 'Kalendar';
			//This is the path for FCKEditor directoy. If you are using FCK Editor, you MUST provide this setting. If not, leave it blank
			cfg.FCKEditorRootPath = '';
			//This is the path to the FCKEditor to use for Kalendar. 
			cfg.FCKEditorCFCPath = "FCKEditor";
			//This is the public http path to the javascript 'scripts' directory. It must end with a slash '/'
			cfg.JavascriptPath = '/kalendar/common/scripts/';
			//This is the public http path to the images directory. It must end with a slash '/'
			cfg.ImagePath = '/kalendar/common/images/';
			//This is the path to the kalendar application. It must end with a slash '/'
			cfg.KalendarURLPath = '/kalendar/';
			//This is the date mask to use for extended (longer) date formatting
			cfg.LongDateMask = 'mmmm d, yyyy';
			//This is the time mask to use for extended (longer) time formatting
			cfg.LongTimeMask = 'hh:mm tt';
			//This is the path to the Administration section of Kalendar
			cfg.KalendarAdminPath = '/kalendar/admin/kalendar/';
			//This is the number of characters to show in event descriptions
			cfg.MaxDescriptionSize = 150;
			//This is the url parameter needed to reload the Kalendar Settings  E.X. index.cfm?init=true 
			cfg.ReloadKey = 'init';
			//This is the value of the url parameter needed to reload the Kalendar Settings
			cfg.ReloadPassword = 'true';
			//This is the email address to use in RSS Feeds
			cfg.RSSWebmaster = 'tdownes@sanative.net';
			//This is the email address to use as Editor in RSS Feeds
			cfg.RssEditor = 'tdownes@sanative.net';
			//This is the date mask to use for abbreviated (short) date formatting
			cfg.ShortDateMask = 'm/d/yy';
			//This is the time mask to use for abbreviated (short) time formatting
			cfg.ShortTimeMask = 'h:mm tt';
			//This is the path for imported files. This should be somewhere the ColdFusion user has write permission. All files will be deleted ater being read. This should end with a slash.
			cfg.TmpImportDirectory = ExpandPath(".") & "/";
			//This is the maximum number of characters of the event title to show in tooltip headers
			cfg.ToolTipSubLength = 40;
			//This controls whether to enable colours for Kalendar Categories
			cfg.UseCategoryColors = true;
			//This is whether or not to use FCKEditor for event entry. FCK Editor is a seperate download. 
			cfg.UseFCKEditor = false;
			//This is the set of valid views
			//cfg.ValidViewList = 'day,weeklist,list,month,week,rss';
			cfg.ValidViewList = 'month,day,weeklist';
			//This is the set of aliases for valid views. Must be in the same order as the ValidViewList
			cfg.ValidViewListAliases = 'Month,Day,Week';
			
			// Call the base init() method to set sensible defaults. Do NOT remove this.
			Super.init();
			// OPTIONAL: Set lazy loading: true or false. If true, Singletons will only be created when requested. If false, they will all be created when LightWire is first initialized. Default if you don't set: LazyLoad = true.
			setLazyLoad("false");
	
			cfg = addExternalConfig( cfg, arguments.ExternalConfigPath, arguments.ExternalConfigSection );
	
			//configuration for KalendarConfig
			addTransient("#cfg.CFCPath#.config.kalendarConfig","KalendarConfig");
			addSetterProperty("KalendarConfig","AdminCSSPath", cfg.AdminCSSPath); 
			addSetterProperty("KalendarConfig","AppTitle", cfg.AppTitle); 
			addSetterProperty("KalendarConfig","CFCPath", cfg.CFCPath); 
			addSetterProperty("KalendarConfig","CSSPath", cfg.CSSPath); 
			addSetterProperty("KalendarConfig","CurrentMode", cfg.CurrentMode); 
			addSetterProperty("KalendarConfig","CustomTagPath", cfg.CustomTagPath); 
			addSetterProperty("KalendarConfig","DBType", cfg.DBType); 
			addSetterProperty("KalendarConfig","DefaultCategoryID", cfg.DefaultCategoryID); 
			addSetterProperty("KalendarConfig","DefaultView", cfg.DefaultView); 
			addSetterProperty("KalendarConfig","DSN", cfg.DSN); 
			addSetterProperty("KalendarConfig","ImagePath", cfg.ImagePath); 
			addSetterProperty("KalendarConfig","JavascriptPath", cfg.JavascriptPath); 
			addSetterProperty("KalendarConfig","KalendarAdminPath", cfg.KalendarAdminPath); 
			addSetterProperty("KalendarConfig","KalendarBuildNumber", cfg.KalendarBuildNumber); 
			addSetterProperty("KalendarConfig","KalendarURLPath", cfg.KalendarURLPath); 
			addSetterProperty("KalendarConfig","LongDateMask", cfg.LongDateMask); 
			addSetterProperty("KalendarConfig","LongTimeMask", cfg.LongTimeMask); 
			addSetterProperty("KalendarConfig","MaxDescriptionSize", cfg.MaxDescriptionSize); 
			addSetterProperty("KalendarConfig","ReloadKey", cfg.ReloadKey); 
			addSetterProperty("KalendarConfig","ReloadPassword", cfg.ReloadPassword); 
			addSetterProperty("KalendarConfig","RssEditor", cfg.RssEditor); 
			addSetterProperty("KalendarConfig","RSSWebmaster", cfg.RSSWebmaster); 
			addSetterProperty("KalendarConfig","ShortDateMask", cfg.ShortDateMask); 
			addSetterProperty("KalendarConfig","ShortTimeMask", cfg.ShortTimeMask); 
			addSetterProperty("KalendarConfig","TmpImportDirectory", cfg.TmpImportDirectory); 
			addSetterProperty("KalendarConfig","ToolTipSubLength", cfg.ToolTipSubLength); 
			addSetterProperty("KalendarConfig","UseCategoryColors", cfg.UseCategoryColors); 
			addSetterProperty("KalendarConfig","UseFCKEditor", cfg.UseFCKEditor); 
			addSetterProperty("KalendarConfig","ValidViewList", cfg.ValidViewList); 
			addSetterProperty("KalendarConfig","ValidViewListAliases", cfg.ValidViewListAliases); 
			
			//configuration for Kalendar.cfc
			addTransient("#cfg.CFCPath#.kalendarDAO", "KalendarDAO");
			addConstructorDependency("KalendarDAO", "KalendarConfig"); 
	
			//configuration for Categories
			addTransient("#cfg.CFCPath#.CategoryDAO","CategoryDAO");
			addConstructorDependency("CategoryDAO", "KalendarConfig"); 

			addTransient("#cfg.CFCPath#.CategoryBean","CategoryBean");
			
				
			//configuration for KalendarRequest
			addTransient("#cfg.CFCPath#.KalendarRequest","KalendarRequest");
			addSetterDependency("KalendarRequest", "KalendarDAO"); 
			addSetterDependency("KalendarRequest", "KalendarConfig"); 
			addSetterDependency("KalendarRequest", "CategoryDAO"); 
			
			addTransient("#cfg.CFCPath#.KalendarEvent","KalendarEvent");
			addSetterDependency("KalendarEvent", "KalendarConfig"); 
			
			//configure validators
			addTransient("#cfg.CFCPath#.KalendarEventValidator","KalendarEventValidator");
			addTransient("#cfg.CFCPath#.CategoryValidator","CategoryValidator");
			
			
			//confguration for commands
			addTransient("#cfg.CFCPath#.commands.SaveRecord", "AddRecord");
			addConstructorDependency("AddRecord", "KalendarDAO"); 
			addConstructorDependency("AddRecord", "CategoryService"); 
			addConstructorDependency("AddRecord", "KalendarEventValidator", "Validator");

			addTransient("#cfg.CFCPath#.commands.DeleteRecord", "DeleteRecord");
			addConstructorDependency("DeleteRecord", "KalendarDAO"); 

			addTransient("#cfg.CFCPath#.commands.SaveRecord", "EditRecord");
			addConstructorDependency("EditRecord", "KalendarDAO"); 
			addConstructorDependency("EditRecord", "CategoryService"); 
			addConstructorDependency("EditRecord", "KalendarEventValidator", "Validator");
			
			addTransient("#cfg.CFCPath#.commands.SaveCategory", "AddCategory");
			addConstructorDependency("AddCategory", "CategoryDAO"); 
			addConstructorDependency("AddCategory", "CategoryValidator", "Validator");
			
			addTransient("#cfg.CFCPath#.commands.DeleteCategory", "DeleteCategory");
			addConstructorDependency("DeleteCategory", "CategoryDAO"); 
			
			addTransient("#cfg.CFCPath#.commands.SaveCategory", "EditCategory");
			addConstructorDependency("EditCategory", "CategoryDAO"); 
			addConstructorDependency("EditCategory", "CategoryValidator", "Validator");
			

			addTransient("#cfg.CFCPath#.commands.NullCommand", "NullCommand");

			addTransient("#cfg.CFCPath#.CommandConfig", "CommandConfig");
			addConstructorDependency("CommandConfig", "NullCommand");
			addConstructorDependency("CommandConfig", "AddRecord");
			addConstructorDependency("CommandConfig", "DeleteRecord");
			addConstructorDependency("CommandConfig", "EditRecord");
			addConstructorDependency("CommandConfig", "AddCategory");
			addConstructorDependency("CommandConfig", "DeleteCategory");
			addConstructorDependency("CommandConfig", "EditCategory");
					
			//Add Config for service
			addTransient("#cfg.CFCPath#.KalendarService", "KalendarService");
			addConstructorDependency("KalendarService", "CommandConfig");
			addSetterDependency("KalendarService", "KalendarDAO"); 		
			addSetterDependency("KalendarService", "CategoryDAO"); 		
			

			addTransient("#cfg.CFCPath#.CategoryService", "CategoryService");
			addSetterDependency("CategoryService", "CategoryDAO");
			addSetterDependency("CategoryService", "LightWire");
			
			
			
			
			if( cfg.UseFCKEditor){
				addTransient( cfg.FCKEditorCFCPath, "FCKEditor");	
			}
			
			//add userMsg container object
			addTransient("#cfg.CFCPath#.UserMsg", "UserMsg");
						
		</cfscript>
		<cfreturn THIS>
	</cffunction>

	<cffunction name="addExternalConfig" access="private" output="false" returntype="struct" hint="I override the default config with settings from the external file and return the configuration struct">
		<cfargument name="Config" type="struct" required="true" />
		<cfargument name="ExternalConfigPath" type="string" default="" />
		<cfargument name="ExternalConfigSection" type="string" default="" />
		<cfset var ConfigSection = arguments.ExternalConfigSection  />		
		<cfset var ConfigData = "" />
			<cfif len( trim( arguments.ExternalConfigPath ) )>
				<cfif NOT len( trim( arguments.ExternalConfigSection ) ) >
					<cfset ConfigSection = "default" />
				</cfif>
				
				<cfset configData = getExternalConfigStruct( expandPath( arguments.ExternalConfigPath ), ConfigSection ) />
				<cfset structAppend( arguments.config, ConfigData ) />

			</cfif>
		
		<cfreturn Config >
	</cffunction>

	<cffunction name="getExternalConfigStruct" access="private" output="false" returntype="struct" hint="I process the config file and return a struct of configs">
		<cfargument name="AbsolutePathToConfig" type="string" required="true" />
		<cfargument name="ExternalConfigSection" type="string" required="true" />
		<cfset var ConfigStruct = structNew() />
		<cfset var ConfigKeys = "" />
		<cfset var thisKey = "" />
			
			<cfset ConfigKeys = structFind( GetProfileSections( arguments.AbsolutePathToConfig ), arguments.ExternalConfigSection ) />

			<cfloop list="#ConfigKeys#" index="thisKey">
				<cfset ConfigStruct[ thisKey ] = trim( getProfileString( arguments.AbsolutePathToConfig, arguments.ExternalConfigSection, thisKey ) ) />	
			</cfloop>

			<cfreturn ConfigStruct />

	</cffunction>

</cfcomponent>